`:top
In `F33f`_`[computing`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Computing]`_`f, `!compile-time function execution`! (or `!compile-time function evaluation`!, or `!general constant expressions`!) is the ability of a `F33f`_`[compiler`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Compiler]`_`f, that would normally compile a `F33f`_`[function`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Subroutine]`_`f to `F33f`_`[machine code`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Machine_code]`_`f and `F33f`_`[execute`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Execution_(computing)]`_`f it at `F33f`_`[run time`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Run_time_(program_lifecycle_phase)]`_`f, to execute the function at `F33f`_`[compile time`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Compile_time]`_`f. This is possible if the arguments to the function are known at compile time, and the function does not make any reference to or attempt to modify any global state (i.e. it is a `F33f`_`[pure function`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Pure_function]`_`f).
If the value of only some of the arguments are known, the compiler may still be able to perform some level of compile-time function execution (`F33f`_`[partial evaluation`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Partial_evaluation]`_`f), possibly producing more optimized code than if no arguments were known.
>>Contents
• `F0af`_`[Examples`#examples]`_`f
• `F0af`_`[Lisp`#lisp]`_`f
• `F0af`_`[C++`#c]`_`f
• `F0af`_`[Immediate functions (C++)`#immediate-functions-c]`_`f
• `F0af`_`[D`#d]`_`f
• `F0af`_`[Zig`#zig]`_`f
• `F0af`_`[References`#references]`_`f
• `F0af`_`[External links`#external-links]`_`f
-─
>>Examples
>>>Lisp
The `F33f`_`[Lisp macro system`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Macro_(computer_science)]`_`f is an early example of the use of compile-time evaluation of user-defined functions in the same language.
>>>C++
The Metacode extension to C++ (Vandevoorde 2003)`:cite-ref-1[`F5bf`_`[1`#cite-note-1]`_`f] was an early experimental system to allow compile-time function evaluation (CTFE) and code injection as an improved syntax for C++ `F33f`_`[template metaprogramming`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Template_metaprogramming]`_`f.
In earlier versions of `F33f`_`[C++`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++]`_`f, `F33f`_`[template metaprogramming`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Template_metaprogramming]`_`f is often used to compute values at compile time, such as:
`B100`F9d9template <int N>`f`b
`B100`F9d9struct Factorial {`f`b
`B100`F9d9 enum { value = N * Factorial<N - 1>::value };`f`b
`B100`F9d9};`f`b
`B100`F9d9`f`b
`B100`F9d9template <>`f`b
`B100`F9d9struct Factorial<0> {`f`b
`B100`F9d9 enum { value = 1 };`f`b
`B100`F9d9};`f`b
`B100`F9d9`f`b
`B100`F9d9// Factorial<4>::value == 24`f`b
`B100`F9d9// Factorial<0>::value == 1`f`b
`B100`F9d9void Foo() {`f`b
`B100`F9d9 int x = Factorial<0>::value; // == 1`f`b
`B100`F9d9 int y = Factorial<4>::value; // == 24`f`b
`B100`F9d9}`f`b
Using compile-time function evaluation, code used to compute the factorial would be similar to what one would write for run-time evaluation e.g. using C++11 constexpr.
`B100`F9d9#include <cstdio>`f`b
`B100`F9d9`f`b
`B100`F9d9constexpr int Factorial(int n) { return n ? (n * Factorial(n - 1)) : 1; }`f`b
`B100`F9d9`f`b
`B100`F9d9constexpr int f10 = Factorial(10);`f`b
`B100`F9d9`f`b
`B100`F9d9int main() {`f`b
`B100`F9d9 printf("%d\\n", f10);`f`b
`B100`F9d9 return 0;`f`b
`B100`F9d9}`f`b
In `F33f`_`[C++11`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++11]`_`f, this technique is known as `F33f`_`[generalized constant expressions`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++11]`_`f (`B100`F9d9constexpr`f`b).`:cite-ref-2[`F5bf`_`[2`#cite-note-2]`_`f] `F33f`_`[C++14`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++14]`_`f `F33f`_`[relaxes the constraints`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++14]`_`f on constexpr – allowing local declarations and use of conditionals and loops (the general restriction that all data required for the execution be available at compile-time remains).
Here's an example of compile-time function evaluation in C++14:
`B100`F9d9// Iterative factorial at compile time.`f`b
`B100`F9d9constexpr int Factorial(int n) {`f`b
`B100`F9d9 int result = 1;`f`b
`B100`F9d9 while (n > 1) {`f`b
`B100`F9d9 result *= n--;`f`b
`B100`F9d9 }`f`b
`B100`F9d9 return result;`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9int main() {`f`b
`B100`F9d9 constexpr int f4 = Factorial(4); // f4 == 24`f`b
`B100`F9d9}`f`b
>>>Immediate functions (C++)
In `F33f`_`[C++20`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=C++20]`_`f, immediate functions were introduced, and compile-time function execution was made more accessible and flexible with relaxed `B100`F9d9constexpr`f`b restrictions.
`B100`F9d9// Iterative factorial at compile time.`f`b
`B100`F9d9consteval int Factorial(int n) {`f`b
`B100`F9d9 int result = 1;`f`b
`B100`F9d9 while (n > 1) {`f`b
`B100`F9d9 result *= n--;`f`b
`B100`F9d9 }`f`b
`B100`F9d9 return result;`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9int main() {`f`b
`B100`F9d9 int f4 = Factorial(4); // f4 == 24`f`b
`B100`F9d9}`f`b
Since function `B100`F9d9Factorial`f`b is marked `B100`F9d9consteval`f`b, it is guaranteed to invoke at compile-time without being forced in another manifestly constant-evaluated context. Hence, the usage of immediate functions offers wide uses in metaprogramming, and compile-time checking (used in C++20 text formatting library).
Here's an example of using immediate functions in compile-time function execution:
`B100`F9d9void you_see_this_error_because_assertion_fails() {}`f`b
`B100`F9d9`f`b
`B100`F9d9consteval void cassert(bool b) {`f`b
`B100`F9d9 if (!b)`f`b
`B100`F9d9 you_see_this_error_because_assertion_fails();`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9consteval void test() {`f`b
`B100`F9d9 int x = 10;`f`b
`B100`F9d9 cassert(x == 10); // ok`f`b
`B100`F9d9 x++;`f`b
`B100`F9d9 cassert(x == 11); // ok`f`b
`B100`F9d9 x--;`f`b
`B100`F9d9 cassert(x == 12); // fails here`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9int main() { test(); }`f`b
In this example, the compilation fails because the immediate function invoked function which is not usable in constant expressions. In other words, the compilation stops after failed assertion.
The typical compilation error message would display:
`B100`F9d9In function 'int main()':`f`b
`B100`F9d9 in 'constexpr' expansion of 'test()'`f`b
`B100`F9d9 in 'constexpr' expansion of 'cassert(x == 12)'`f`b
`B100`F9d9error: call to non-'constexpr' function 'you_see_this_error_because_assertion_fails()'`f`b
`B100`F9d9 you_see_this_error_because_assertion_fails();`f`b
`B100`F9d9 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~`f`b
`B100`F9d9 [ ... ]`f`b
Here's another example of using immediate functions as constructors which enables compile-time argument checking:
`B100`F9d9#include <string_view>`f`b
`B100`F9d9#include <iostream>`f`b
`B100`F9d9`f`b
`B100`F9d9void you_see_this_error_because_the_message_ends_with_exclamation_point() {}`f`b
`B100`F9d9`f`b
`B100`F9d9struct checked_message {`f`b
`B100`F9d9 std::string_view msg;`f`b
`B100`F9d9`f`b
`B100`F9d9 consteval checked_message(const char* arg)`f`b
`B100`F9d9 : msg(arg) {`f`b
`B100`F9d9 if (msg.ends_with('!'))`f`b
`B100`F9d9 you_see_this_error_because_the_message_ends_with_exclamation_point();`f`b
`B100`F9d9 }`f`b
`B100`F9d9};`f`b
`B100`F9d9`f`b
`B100`F9d9void send_calm_message(checked_message arg) {`f`b
`B100`F9d9 std::cout << arg.msg << '\\n';`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9int main() {`f`b
`B100`F9d9 send_calm_message("Hello, world");`f`b
`B100`F9d9 send_calm_message("Hello, world!");`f`b
`B100`F9d9}`f`b
The compilation fails here with the message:
`B100`F9d9In function 'int main()':`f`b
`B100`F9d9 in 'constexpr' expansion of 'checked_message(((const char*)"Hello, world!"))'`f`b
`B100`F9d9error: call to non-'constexpr' function 'void you_see_this_error_because_the_message_ends_with_exclamation_point()'`f`b
`B100`F9d9 you_see_this_error_because_the_message_ends_with_exclamation_point();`f`b
`B100`F9d9 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~`f`b
`B100`F9d9 [ ... ]`f`b
>>>D
Here's an example of compile-time function evaluation in the `F33f`_`[D programming language`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=D_programming_language]`_`f:`:cite-ref-3[`F5bf`_`[3`#cite-note-3]`_`f]
`B100`F9d9int factorial(int n) {`f`b
`B100`F9d9 if (n == 0)`f`b
`B100`F9d9 return 1;`f`b
`B100`F9d9 return n * factorial(n - 1);`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9// computed at compile time`f`b
`B100`F9d9enum y = factorial(0); // == 1`f`b
`B100`F9d9enum x = factorial(4); // == 24`f`b
This example specifies a valid D function called "factorial" which would typically be evaluated at run time. The use of `B100`F9d9enum`f`b tells the compiler that the initializer for the variables must be computed at compile time. Note that the arguments to the function must be able to be resolved at compile time as well.`:cite-ref-4[`F5bf`_`[4`#cite-note-4]`_`f]
CTFE can be used to populate data structures at compile-time in a simple way (D version 2):
`B100`F9d9int[] genFactorials(int n) {`f`b
`B100`F9d9 auto result = new int[n];`f`b
`B100`F9d9 result[0] = 1;`f`b
`B100`F9d9 foreach (i; 1 .. n)`f`b
`B100`F9d9 result[i] = result[i - 1] * i;`f`b
`B100`F9d9 return result;`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9enum factorials = genFactorials(13);`f`b
`B100`F9d9`f`b
`B100`F9d9void main() {}`f`b
`B100`F9d9`f`b
`B100`F9d9// 'factorials' contains at compile-time:`f`b
`B100`F9d9// [1, 1, 2, 6, 24, 120, 720, 5_040, 40_320, 362_880, 3_628_800,`f`b
`B100`F9d9// 39_916_800, 479_001_600]`f`b
CTFE can be used to generate strings which are then parsed and compiled as D code in D.
>>>Zig
Here's an example of compile-time function evaluation in the `F33f`_`[Zig programming language`:/page/wikibook/entry.mu`zim=wikipedia_en_all_nopic_2025-08.zim|entry_path=Zig_programming_language]`_`f:`:cite-ref-5[`F5bf`_`[5`#cite-note-5]`_`f]
`B100`F9d9pub fn factorial(n: usize) usize {`f`b
`B100`F9d9 var result = 1;`f`b
`B100`F9d9 for (1..(n + 1)) |i| {`f`b
`B100`F9d9 result *= i;`f`b
`B100`F9d9 }`f`b
`B100`F9d9 return result;`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9pub fn main() void {`f`b
`B100`F9d9 const x = comptime factorial(0); // == 0`f`b
`B100`F9d9 const y = comptime factorial(4); // == 24`f`b
`B100`F9d9}`f`b
This example specifies a valid Zig function called "factorial" which would typically be evaluated at run time. The use of `B100`F9d9comptime`f`b tells the compiler that the initializer for the variables must be computed at compile time. Note that the arguments to the function must be able to be resolved at compile time as well.
Zig also support Compile-Time Parameters.`:cite-ref-6[`F5bf`_`[6`#cite-note-6]`_`f]
`B100`F9d9pub fn factorial(comptime n: usize) usize {`f`b
`B100`F9d9 var result: usize = 1;`f`b
`B100`F9d9 for (1..(n + 1)) |i| {`f`b
`B100`F9d9 result *= i;`f`b
`B100`F9d9 }`f`b
`B100`F9d9 return result;`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9pub fn main() void {`f`b
`B100`F9d9 const x = factorial(0); // == 0`f`b
`B100`F9d9 const y = factorial(4); // == 24`f`b
`B100`F9d9}`f`b
CTFE can be used to create generic data structures at compile-time:
`B100`F9d9fn List(comptime T: type) type {`f`b
`B100`F9d9 return struct {`f`b
`B100`F9d9 items: []T,`f`b
`B100`F9d9 len: usize,`f`b
`B100`F9d9 };`f`b
`B100`F9d9}`f`b
`B100`F9d9`f`b
`B100`F9d9// The generic List data structure can be instantiated by passing in a type:`f`b
`B100`F9d9var buffer: [10]i32 = undefined;`f`b
`B100`F9d9var list = List(i32){`f`b
`B100`F9d9 .items = &buffer,`f`b
`B100`F9d9 .len = 0,`f`b
`B100`F9d9};`f`b
>>References
`:cite-note-1`!1.`! `F0af`_`[↑`#cite-ref-1]`_`f `:citerefdaveed-vandevoorde-edison-design-group2003`aDaveed Vandevoorde, Edison Design Group (April 18, 2003). "Reflective Metaprogramming in C++" (PDF). Retrieved July 19, 2015.
`:cite-note-2`!2.`! `F0af`_`[↑`#cite-ref-2]`_`f `:citerefgabriel-dos-reis-and-bjarne-stroustrup2010`aGabriel Dos Reis and Bjarne Stroustrup (March 2010). "General Constant Expressions for System Programming Languages. SAC-2010. The 25th ACM Symposium On Applied Computing" (PDF).
`:cite-note-3`!3.`! `F0af`_`[↑`#cite-ref-3]`_`f D 2.0 language specification: Functions
`:cite-note-4`!4.`! `F0af`_`[↑`#cite-ref-4]`_`f D 2.0 language specification: Attributes
`:cite-note-5`!5.`! `F0af`_`[↑`#cite-ref-5]`_`f Zig 0.11.0 Language Reference: Compile-Time Expressions
`:cite-note-6`!6.`! `F0af`_`[↑`#cite-ref-6]`_`f Zig 0.11.0 Language Reference: Compile-Time Parameters
>>External links
• Rosettacode examples of compile-time function evaluation in various languages
`c`F0af`_`[↑ Back to top`#top]`_`f`a